#include <stdlib.h> // For rand()
#include <unistd.h> // For sleep
#include <pthread.h>
#include <semaphore.h>
#include <string.h> // For sprintf, strlen, strncpy
#include <time.h>   // For time()
#include "Writer.h"
#include "ReaderWriterUtilities.h"

// Function executed by writer threads
void *writerThread(void *arg) {
    ThreadStruct_t *curThreadStruct = (ThreadStruct_t *)arg;
    ReaderWriterManager_t *rwMgr = curThreadStruct->rwMgr;
    int threadIdx = curThreadStruct->threadIdx;
    char localBuffer[MAX_WRITE_LEN + 1]; // Buffer for creating the message

    printf("Writer %d starting.\n", threadIdx);
    srand(time(NULL) ^ pthread_self()); // Seed random number generator per thread

    while (rwMgr->exit_flag == 0) { // Check exit flag [Source 27, 59] similar loop

        // 写者进入协议
        // 尝试获取 rw_mutex。如果该信号量已被其他写者或任何读者持有（因为第一个读者会持有它），则写者在此阻塞。
        semWait(&rwMgr->rw_mutex); // 成功获取意味着获得了对共享缓冲区的独占访问权。
        


        // 临界区
        // Only one writer can be here at a time, and no readers.
        printf("Writer %d ENTERED critical section. Writing...\n", threadIdx);
        // Create some data to write
        int writeLen = snprintf(localBuffer, MAX_WRITE_LEN, "Msg from W%d @ %ld",
                                threadIdx, time(NULL));
        if (writeLen < 0) writeLen = 0; // Handle snprintf error
        if (writeLen >= BUFFER_SIZE) writeLen = BUFFER_SIZE - 1; // Prevent overflow
	
	//将数据复制到共享缓冲区 (strncpy)，更新 buffer_len。
        strncpy(rwMgr->buffer, localBuffer, writeLen);
        rwMgr->buffer[writeLen] = '\0'; // Null-terminate
        rwMgr->buffer_len = writeLen;   // Update length

        printf("Writer %d wrote: \"%s\"\n", threadIdx, rwMgr->buffer);
        // Simulate writing time
        sleep(WAIT_TIME_IN_SECOND);
        printf("Writer %d EXITING critical section.\n", threadIdx);
        // --- End Critical Section ---


        // --- Writer Exit Protocol ---
        semSignal(&rwMgr->rw_mutex); //  释放 rw_mutex，允许其他等待的读者（如果是第一个）或写者进入。
        // --- End Writer Exit Protocol ---

        // Simulate time between writes
        sleep(WAIT_TIME_IN_SECOND + (rand() % (WAIT_TIME_IN_SECOND * 2)));
    }

    printf("Writer %d exiting.\n", threadIdx);
    return NULL;
}
